﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using Csla;
using Csla.Data;
using Csla.Serialization;

namespace Authentication
{
    [Serializable()]
    public partial class CustomIdentity : ReadOnlyBase<CustomIdentity>, IIdentity
    {
        #region Business Method & Identity member
        private static PropertyInfo<string> RolesProperty = RegisterProperty<string>(p => p.Roles);
        public string Roles
        {
            get { return ReadProperty(RolesProperty); }
            private set { LoadProperty(RolesProperty, value); }
        }

        private static PropertyInfo<string> PermissionsProperty = RegisterProperty<string>(p => p.Permissions);
        public string Permissions
        {
            get { return ReadProperty(PermissionsProperty); }
            private set { LoadProperty(PermissionsProperty, value); }
        }

        private static PropertyInfo<int> IDProperty = RegisterProperty<int>(p => p.ID);
        public int ID
        {
            get { return ReadProperty(IDProperty); }
            private set { LoadProperty(IDProperty, value); }
        }

        private static PropertyInfo<string> NameProperty = RegisterProperty<string>(p => p.Name);
        public string Name
        {
            get { return ReadProperty(NameProperty); }
            private set { LoadProperty(NameProperty, value); }
        }

        private static PropertyInfo<bool> IsAuthenticatedProperty = RegisterProperty<bool>(p => p.IsAuthenticated);
        public bool IsAuthenticated
        {
            get { return ReadProperty(IsAuthenticatedProperty); }
            private set { LoadProperty(IsAuthenticatedProperty, value); }
        }

        private static PropertyInfo<string> AuthenticationTypeProperty = RegisterProperty<string>(p => p.AuthenticationType);
        public string AuthenticationType
        {
            get { return ReadProperty(AuthenticationTypeProperty); }
            private set { LoadProperty(AuthenticationTypeProperty, value); }
        }
        #endregion

        #region Custom methods
        public bool IsInRole(string role)
        {
            return HasPermission(role);
        }

        public bool HasPermission(string permission)
        {
            string[] listOfPermissons = Permissions.Split(',');
            return listOfPermissons.Contains(permission);
        }

        protected override void AddBusinessRules()
        {
            base.AddBusinessRules();
        }
        #endregion

        #region Factory Methods
        public static void Login(string userName, string password, EventHandler<DataPortalResult<CustomIdentity>> callback)
        {
            var dp = new DataPortal<CustomIdentity>();
            dp.FetchCompleted += callback;
            dp.BeginFetch(new Csla.Security.UsernameCriteria(userName, password), callback);
        }

#if !SILVERLIGHT
        public static CustomIdentity Login(Csla.Security.UsernameCriteria criteria)
        {
            return DataPortal.Fetch<CustomIdentity>(criteria);
        }
#else
        public CustomIdentity()
        { /* require by MobileFormatter */ }
#endif
        #endregion

        #region Root object data acess
#if !SILVERLIGHT
        [Transactional(TransactionalTypes.TransactionScope)]
        private void DataPortal_Fetch(Csla.Security.UsernameCriteria criteria)
        {
            try
            {
                using (var ctx =
                    ContextManager<Accounting.DataAccess.AccountingDataContext>.
                    GetManager(Accounting.DataAccess.Database.Accounting))
                {
                    var q = (from r in ctx.DataContext.HT_NguoiDungs
                             where (r.TenDangNhap == criteria.Username && r.MatKhau == criteria.Password)
                             select r).FirstOrDefault();
                    if (q != null)
                    {
                        string roles = "";
                        string permissions = "";

                        q.HT_NguoiDung_VaiTros.Load();
                        foreach (var r in q.HT_NguoiDung_VaiTros)
                        {
                            roles += r.HT_VaiTro.Ma + ",";
                            r.HT_VaiTro.HT_VaiTro_QuyenHans.Load();
                            foreach (var p in r.HT_VaiTro.HT_VaiTro_QuyenHans)
                                if (!permissions.Contains(p.HT_QuyenHan.TenViet))
                                    permissions += p.HT_QuyenHan.TenViet + ",";
                        }

                        roles = roles.Substring(0, roles.Length - 1);
                        permissions = permissions.Substring(0, permissions.Length - 1);

                        LoadProperty(RolesProperty, roles);
                        LoadProperty(PermissionsProperty, permissions);
                        LoadProperty(IDProperty, q.Khoa);
                        LoadProperty(NameProperty, q.TenDangNhap);
                        LoadProperty(IsAuthenticatedProperty, true);
                        LoadProperty(AuthenticationTypeProperty, "Custom");
                    }
                    else
                    {
                        LoadProperty(IsAuthenticatedProperty, false);
                        LoadProperty(AuthenticationTypeProperty, "Custom");
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
#endif
        #endregion
    }
}
